Kolesár András adds faster Garmin serial download speed option.
authorrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 12 May 2014 00:08:59 +0000 (00:08 +0000)
committerrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 12 May 2014 00:08:59 +0000 (00:08 +0000)
gpsbabel/garmin.cc
gpsbabel/gbser_posix.cc
gpsbabel/jeeps/gps.h
gpsbabel/jeeps/gpsapp.cc
gpsbabel/jeeps/gpsapp.h
gpsbabel/jeeps/gpscom.cc
gpsbabel/jeeps/gpsserial.cc
gpsbabel/jeeps/gpsserial.h
gpsbabel/jeeps/gpsusbread.cc
gpsbabel/jeeps/gpsusbsend.cc
gpsbabel/xmldoc/formats/options/garmin-baud.xml [new file with mode: 0644]

index d2489fbff09977a9a568ad342e7a0b61a033daf9..bb629a452d48f8d0a1ddbbc630769cb2f781e318 100644 (file)
@@ -26,6 +26,7 @@
 #include "defs.h"
 #include "grtcirc.h"
 #include "jeeps/gps.h"
+#include "jeeps/gpsserial.h"
 #include "garmin_tables.h"
 #include "garmin_fs.h"
 #include "garmin_device_xml.h"
@@ -48,6 +49,8 @@ static char* snwhiteopt = NULL;
 static char* deficon = NULL;
 static char* category = NULL;
 static char* categorybitsopt = NULL;
+static char* baudopt = NULL;
+static int baud = 0;
 static int categorybits;
 static int receiver_must_upper = 1;
 
@@ -93,6 +96,10 @@ arglist_t garmin_args[] = {
     "bitscategory", &categorybitsopt, "Bitmap of categories",
     NULL, ARGTYPE_INT, "1", "65535"
   },
+  {
+    "baud", &baudopt, "Speed in bits per second of serial port (baud=9600)",
+    NULL, ARGTYPE_INT, ARG_NOMINMAX },
+
   ARG_TERMINATOR
 };
 
@@ -139,11 +146,31 @@ rw_init(const char* fname)
     categorybits = strtol(categorybitsopt, NULL, 0);
   }
 
+  if (baudopt) {
+    baud = strtol(baudopt, NULL, 0);
+    switch (baud) {
+      case 9600:
+      case 19200:
+      case 38400:
+      case 57600:
+      case 115200:
+        break;
+      default:
+        fatal("Baud rate %d is not supported\n", baud);
+    }
+  }
+
   if (GPS_Init(fname) < 0) {
     fatal(MYNAME ":Can't init %s\n", fname);
   }
   portname = fname;
 
+  if (baud && baud != DEFAULT_BAUD) {
+    if (0 == GPS_Set_Baud_Rate(portname, baud)) {
+      gps_baud_rate = baud;
+    }
+  }
+
   /*
    * Grope the unit we're talking to to set setshort_length to
    *   20 for  the V,
@@ -314,6 +341,12 @@ rd_init(const char* fname)
 static void
 rw_deinit(void)
 {
+  if (gps_baud_rate != DEFAULT_BAUD) {
+    if (0 == GPS_Set_Baud_Rate(portname, DEFAULT_BAUD)) {
+      gps_baud_rate = baud;
+    }
+  }
+  
   if (mkshort_handle) {
     mkshort_del_handle(&mkshort_handle);
   }
index b4939b0952eea4369b0b6f7066cca6eba705205f..3ae1522a398086f58f84403ec3803e1f9a9f0014 100644 (file)
@@ -51,7 +51,7 @@ static gbser_handle* gbser__get_handle(void* p)
   return h;
 }
 
-static speed_t mkspeed(unsigned br)
+speed_t mkspeed(unsigned br)
 {
   switch (br) {
   case   1200:
index 7da64b6be895624d7ffab41ce5af6aa4086b3de0..ddcc1b654111255fd7309f2c8a418b3a533e40e6 100644 (file)
@@ -276,6 +276,7 @@ extern int32  gps_save_id;
 extern double gps_save_version;
 extern char   gps_save_string[GPS_ARB_LEN];
 extern int gps_is_usb;
+extern int gps_baud_rate;
 
 extern struct COMMANDDATA COMMAND_ID[2];
 extern struct LINKDATA LINK_ID[3];
index 17e7002e9d8bba0fa2f6df58798d36d2f9deccf5..ebebfe5546d5987d566e54efb5ccae301d65ed27 100644 (file)
@@ -36,6 +36,7 @@
  */
 #include "garminusb.h"
 #include "gpsusbint.h"
+#include "gpsserial.h"
 
 time_t gps_save_time;
 double gps_save_lat;
@@ -3655,7 +3656,7 @@ static void GPS_D210_Send(UC* data, GPS_PWay way, int32* len)
 **
 ** @return [int32] number of track entries
 ************************************************************************/
-int32 GPS_A300_Get(const char* port, GPS_PTrack** trk, pcb_fn cb)
+int32 GPS_A300_Get(const char* port , GPS_PTrack** trk, pcb_fn)
 {
   static UC data[2];
   gpsdevh* fd;
@@ -6176,7 +6177,7 @@ int32 GPS_A800_On(const char* port, gpsdevh** fd)
 **
 ** @return [int32] success
 ************************************************************************/
-int32 GPS_A800_Off(const char* port, gpsdevh** fd)
+int32 GPS_A800_Off(const char*, gpsdevh** fd)
 {
   static UC data[2];
   GPS_PPacket tra;
@@ -6638,7 +6639,7 @@ int32  GPS_A1006_Get
 **
 ** @return [int32] success
 ************************************************************************/
-int32 GPS_A1006_Send(const char* port,
+int32 GPS_A1006_Send(const char*,
                      GPS_PCourse* crs,
                      int32 n_crs,
                      gpsdevh* fd)
@@ -6875,7 +6876,7 @@ int32 GPS_A1007_Get(const char* port, GPS_PCourse_Lap** clp, pcb_fn cb)
 **
 ** @return [int32] success
 ************************************************************************/
-int32 GPS_A1007_Send(const char* port,
+int32 GPS_A1007_Send(const char*,
                      GPS_PCourse_Lap* clp,
                      int32 n_clp,
                      gpsdevh* fd)
@@ -7150,7 +7151,7 @@ int32 GPS_A1008_Get(const char* port, GPS_PCourse_Point** cpt, pcb_fn cb)
 **
 ** @return [int32] success
 ************************************************************************/
-int32 GPS_A1008_Send(const char* port,
+int32 GPS_A1008_Send(const char*,
                      GPS_PCourse_Point* cpt,
                      int32 n_cpt,
                      gpsdevh* fd)
@@ -7641,3 +7642,23 @@ void GPS_Prepare_Track_For_Device(GPS_PTrack** trk, int32* n)
     }
   }
 }
+
+int32 GPS_Set_Baud_Rate(const char* port, int br)
+{
+
+  gpsdevh* fd;
+  
+  if (!GPS_Device_On(port, &fd)) {
+    return gps_errno;
+  }
+
+  if (gps_is_usb) return -1; // this feature is serial only
+  GPS_Serial_Set_Baud_Rate(fd, br);
+
+  if (!GPS_Device_Off(fd)) {
+    return gps_errno;
+  }
+  
+  return 0;
+
+}
index 7933a43ca5e8db72f794f07cafe401e5a17aeba5..f9e9b17ab6bcb4b75f16e1e9d32adbd70e4efc67 100644 (file)
   const char* Get_Pkt_Type(US p, US d0, const char** xinfo);
 
   void GPS_Prepare_Track_For_Device(GPS_PTrack** trk, int32* n);
+  int32 GPS_Set_Baud_Rate(const char* port, int br);
 
 #endif
index 8caa2f1a1c186ec36aedee46e8ae295c054e1308..bcd686df90707ba69e0d1b5b761558723cc5cdf2 100644 (file)
@@ -1306,7 +1306,7 @@ int32 GPS_Command_Send_Track_As_Course(const char* port, GPS_PTrack* trk, int32
 }
 
 /*Stubs for unimplemented stuff*/
-int32  GPS_Command_Get_Workout(const char* port, void** lap, int (*cb)(int, struct GPS_SWay**))
+int32  GPS_Command_Get_Workout(const char*, void**, int (*cb)(int, struct GPS_SWay**))
 {
   return 0;
 }
index 19ef8f8fd68cdf8b0fb45f17d2d33799aa8650b6..0e0c4a031dc69b2fad485267b8bf46011ea2a6ca 100644 (file)
@@ -33,6 +33,8 @@
 #include <stdio.h>
 #include <time.h>
 
+int gps_baud_rate = DEFAULT_BAUD;
+
 #if 0
 #define GARMULATOR 1
 char* rxdata[] = {
@@ -226,6 +228,7 @@ int32 GPS_Serial_Read(gpsdevh* dh, void* ibuf, int size)
 
 #else
 
+#include "../gbser_posix.h"
 #include <sys/ioctl.h>
 #include <sys/time.h>
 #include <termios.h>
@@ -249,6 +252,8 @@ typedef struct {
 int32 GPS_Serial_Open(gpsdevh* dh, const char* port)
 {
   struct termios tty;
+  if (global_opts.debug_level >= 2) fprintf(stderr, "GPS Serial Open at %d\n", gps_baud_rate);
+  speed_t baud = mkspeed(gps_baud_rate);
   posix_serial_data* psd = (posix_serial_data*)dh;
 
   /*
@@ -272,8 +277,8 @@ int32 GPS_Serial_Open(gpsdevh* dh, const char* port)
 
   tty.c_cflag &= ~(CSIZE);
   tty.c_cflag |= (CREAD | CS8 | CLOCAL);
-  cfsetospeed(&tty,B9600);
-  cfsetispeed(&tty,B9600);
+  cfsetospeed(&tty,baud);
+  cfsetispeed(&tty,baud);
 
   tty.c_lflag &= 0x0;
   tty.c_iflag &= 0x0;
@@ -527,4 +532,87 @@ int32 GPS_Serial_Off(gpsdevh* dh)
   return 1;
 }
 
+// Based on information by Kolesár András from
+// http://www.manualslib.com/manual/413938/Garmin-Gps-18x.html?page=32
+int32 GPS_Serial_Set_Baud_Rate(gpsdevh* fd, int br)
+{
+
+  struct termios tty;
+  static UC data[4];
+  GPS_PPacket tra;
+  GPS_PPacket rec;
+  speed_t speed;
+  
+  speed = mkspeed(br);
+
+  // Turn off all requests by transmitting packet
+  GPS_Util_Put_Short(data, 0);
+  GPS_Make_Packet(&tra, 0x1c, data, 2);
+  if (!GPS_Write_Packet(fd,tra)) {
+    return gps_errno;
+  }
+  if (!GPS_Get_Ack(fd, &tra, &rec)) {
+    return gps_errno;
+  }
+  
+  GPS_Util_Put_Int(data, br);
+  GPS_Make_Packet(&tra, 0x30, data, 4);
+  if (!GPS_Write_Packet(fd,tra)) {
+    return gps_errno;
+  }
+  if (!GPS_Get_Ack(fd, &tra, &rec)) {
+    return gps_errno;
+  }
+
+  // Receive IOP_BAUD_ACPT_DATA
+  if (!GPS_Packet_Read(fd, &rec)) {
+    return gps_errno;
+  }
+
+  // Acnowledge new speed
+  if (!GPS_Send_Ack(fd, &tra, &rec)) {
+    return gps_errno;
+  }
+  GPS_Device_Flush(fd);
+  GPS_Device_Wait(fd);
+  
+  // Sleep for a small amount of time, about 100 milliseconds,
+  // to make sure the packet was successfully transmitted to the GPS unit.
+  gb_sleep(100000); 
+  
+  // Change port speed
+  posix_serial_data* psd = (posix_serial_data*)fd;
+  tty = psd->gps_ttysave;
+  
+  cfsetospeed(&tty,speed);
+  cfsetispeed(&tty,speed);
+  
+  if (tcsetattr(psd->fd,TCSANOW|TCSAFLUSH,&tty)==-1) {
+    GPS_Serial_Error("SERIAL: tcsetattr error");
+    return 0;
+  }
+  
+  GPS_Util_Put_Short(data, 0x3a);
+  GPS_Make_Packet(&tra, 0x0a, data, 2);
+  if (!GPS_Write_Packet(fd,tra)) {
+    return gps_errno;
+  }
+  if (!GPS_Get_Ack(fd, &tra, &rec)) {
+    return gps_errno;
+  }
+
+  GPS_Util_Put_Short(data, 0x3a);
+  GPS_Make_Packet(&tra, 0x0a, data, 2);
+  if (!GPS_Write_Packet(fd,tra)) {
+    return gps_errno;
+  }
+  if (!GPS_Get_Ack(fd, &tra, &rec)) {
+    return gps_errno;
+  }
+  
+  if (global_opts.debug_level >= 1) fprintf(stderr, "Serial port speed set to %d\n", br);
+  return 0;
+  
+}
+
 #endif /* __WIN32__ */
index 9507ded8cd656c97b5898a56e3e97c776af86fec..a9f13dae34009c79db8291826da239293f9e704a 100644 (file)
@@ -5,6 +5,7 @@
 #include "gps.h"
 
 #define usecDELAY 180000       /* Microseconds before GPS sends A001 */
+#define DEFAULT_BAUD 9600
 
   int32  GPS_Serial_Chars_Ready(gpsdevh* fd);
 // int32  GPS_Serial_Close(int32 fd, const char *port);
@@ -22,6 +23,6 @@
   int32  GPS_Serial_Write_Packet(gpsdevh* fd, GPS_PPacket& packet);
   int32  GPS_Serial_Send_Ack(gpsdevh* fd, GPS_PPacket* tra, GPS_PPacket* rec);
   void   GPS_Serial_Error(const char* hdr, ...);
-
+  int32  GPS_Serial_Set_Baud_Rate(gpsdevh* fd, int br);
 
 #endif
index 5e392beee7c50d741f8c8157df3d7aa3a30abdfe..233f085875336f1584eb01e6940c34dd71fcf0fe 100644 (file)
@@ -28,7 +28,7 @@
  * Negative on error.
  * 1 if read success - even if empty packet.
  */
-int32 GPS_Packet_Read_usb(gpsdevh* dh, GPS_PPacket* packet, int eat_bulk)
+int32 GPS_Packet_Read_usb(gpsdevh*, GPS_PPacket* packet, int eat_bulk)
 {
   int32  n;
   int32 payload_size;
index 45c0edef6af7f86208c904a28202e1c99fb06580..de433adff3dc98f9626710592224888f4d919aee 100644 (file)
@@ -26,7 +26,7 @@
 #include "gpsusbint.h"
 
 int32
-GPS_Write_Packet_usb(gpsdevh* dh, GPS_PPacket& packet)
+GPS_Write_Packet_usb(gpsdevh*, GPS_PPacket& packet)
 {
   garmin_usb_packet gp;
   memset(&gp, 0, sizeof(gp));
diff --git a/gpsbabel/xmldoc/formats/options/garmin-baud.xml b/gpsbabel/xmldoc/formats/options/garmin-baud.xml
new file mode 100644 (file)
index 0000000..04eb09b
--- /dev/null
@@ -0,0 +1,28 @@
+<para>
+Sets baud rate on some Garmin serial unit to the specified baud rate. Garmin protocol uses 9600 bps by default, but there is a rarely documented feature in Garmin binary protocol for switching baud rate. Highest option is 115200.
+</para>
+
+<para>
+Download track log and waypoints 12 times faster than default:
+<userinput>
+gpsbabel -t -w -i garmin,baud=115200 -f /dev/ttyUSB0 -o gpx -F garmin-serial.gpx
+</userinput>
+</para>
+
+<para>
+At the end of the transfer, baud rate is switched to back to the default 
+of 9600. If connection breaks, the unit stucks at high baud rate, a power 
+cycle reverts to original state.
+</para>
+
+<para>
+This option does not affect USB transfer.
+</para>
+
+<para>
+Because this feature uses undocumented Garmin protocols, it may or may
+not work on your device.  The author reported success with 
+eTrex Vista, GPSMAP 76s, and GPS V, but it seems likely to be problematic
+on older units and may be more problematic for writing to the device than
+reading data from the device.
+</para>